package cc.wd.demo.blockchain.utils;

import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.Base64;

/**
 * @author wudi
 * @date 2018/4/4.
 */
public class SecureUtil {
    private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
    private static final char[] HEX_DIGITS_LOW = "0123456789abcdef".toCharArray();

    public static String MD5(String s) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] bytes = md.digest(s.getBytes("UTF-8"));
            return toHexLower(bytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String toUpperCaseMD5(String s) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] bytes = md.digest(s.getBytes("UTF-8"));
            return toHexUpper(bytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String Sha256(String s) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] digest = md.digest(s.getBytes("UTF-8"));
            return toHexUpper(digest);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return s;
    }

    private static String toHexLower(byte[] bytes) {
        StringBuilder ret = new StringBuilder(bytes.length * 2);
        for (byte aByte : bytes) {
            ret.append(HEX_DIGITS_LOW[(aByte >> 4) & 0x0f]);
            ret.append(HEX_DIGITS_LOW[aByte & 0x0f]);
        }
        return ret.toString();
    }

    private static String toHexUpper(byte[] bytes) {
        StringBuilder ret = new StringBuilder(bytes.length * 2);
        for (byte aByte : bytes) {
            ret.append(HEX_DIGITS[(aByte >> 4) & 0x0f]);
            ret.append(HEX_DIGITS[aByte & 0x0f]);
        }
        return ret.toString();
    }


    public static byte[] applyRSASignature(PrivateKey privateKey, String input) {
        Signature rsa;
        byte[] output;
        try {
            rsa = Signature.getInstance("SHA1WithRSA");
            rsa.initSign(privateKey);
            byte[] strByte = input.getBytes();
            rsa.update(strByte);
            output = rsa.sign();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return output;
    }

    public static boolean verifyRSASignature(PublicKey publicKey, String data, byte[] signature) {
        try {
            Signature rsaVerify = Signature.getInstance("SHA1WithRSA");
            rsaVerify.initVerify(publicKey);
            rsaVerify.update(data.getBytes());
            return rsaVerify.verify(signature);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String getStringFromKey(Key key) {
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }

}
